from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
import pickle

# 加载数字数据集
digits = datasets.load_digits()
X=digits.data #获取样本数据
y=digits.target #获取样本标签

# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 初始化变量以存储最佳准确率，相应的k值和最佳knn模型
best_accuracy = 0
best_k = 0
best_knn_model = None

# 初始化一个列表以存储每个k值的准确率
accuracies = []

# 尝试从1到40的k值，对于每个k值，训练knn模型，保存最佳准确率，k值和knn模型
for k in range(1, 41):  #这个循环迭代k值从1-40，每次尝试不同的k值
    knn = KNeighborsClassifier(n_neighbors=k) #创建knn分类器，k值为当前迭代的k值
    knn.fit(X_train, y_train) #使用训练数据“X_train”和“y_train”来训练knn模型
    y_predict = knn.predict(X_test) #用训练好的knn模型对测试数据“X_test”进行预测，将结果存储在“y_pred”
    accuracy = accuracy_score(y_test, y_predict) #计算预测准确率
    accuracies.append(accuracy) #将每个k值下的准确率添加到“accuracies”列表中
    if accuracy > best_accuracy: #如果当前准确率大于最佳准确率，则更新最佳准确率，相应的k值和最佳knn模型
        best_accuracy = accuracy
        best_k = k
        best_knn_model = knn

# 将最佳KNN模型保存到二进制文件,并存在E盘根目录下
with open('E:/best_knn_model.pkl', 'wb') as file:
    pickle.dump(best_knn_model, file)
# 打印最佳准确率和相应的k值
print(f'Best Accuracy: {best_accuracy}, Best k: {best_k}')

#打印过程进度条
from tqdm import tqdm  
import numpy as np  
import time  
# 使用numpy的linspace函数生成一个列表，指定起始值、结束值和元素个数
start = 0 
end = 10  
num_elements = 100  # 元素个数
linspace_list = np.linspace(start, end, num_elements)  # 生成列表
# 使用tqdm创建进度条，并遍历linspace_list中的元素
for element in tqdm(linspace_list, unit="每秒的单位"):  
    time.sleep(0.1)  # 延时0.1秒

#绘制折线图，横坐标为k值，纵坐标为准确率，添加标题和标签,设置颜色为蓝色
import matplotlib.pyplot as plt
plt.plot(range(1, 41), accuracies,color='b')
plt.title('Accuracy of diffierent k values')
plt.xlabel('k')
plt.ylabel('Accuracy')
#绘制垂线，标记最佳准确率对应的k值
plt.plot(range(1, 41), accuracies)
plt.xlabel('k')
plt.ylabel('Accuracy')
plt.axvline(6,color='r')  #0.97和0.99分别是y轴的最小值和最大值
#绘制文字，标记最佳准确率对应的k值
plt.text(best_k, best_accuracy, f'k={best_k}, accuracy={best_accuracy}')
#保存pdf文件在E盘根目录下
plt.savefig('E:/accuracy_plot.pdf')
#显示图形
plt.show()

